// 为使用arm-linux-gnueabi-gcc交叉编译工具，本文件采用GNU ARM汇编格式
// 官方ARM汇编格式的伪操作在注释中写出
// GNU ARM汇编使用 "//" 作为行注释起点，而ARM汇编使用';'作为行注释起点 


// AREA data, DATA, READWRITE
.data 

// printf与scanf使用的格式化字符串
printfstr1: .asciz "a b c d = "
scanfstr:   .asciz "%d%d%d%d"
printfstr2: .asciz "x=%d, y=%d, z=%d\n"

// AREA code, CODE, READONLY
.text

// 将符号main暴露给外部，便于程序入口函数_start调用
.globl main 

// main函数入口
main:   stmfd   sp!, {lr}       // 返回地址压栈
        ldr     r0, =printfstr1 // printf argument 1
        bl      printf          // 函数调用printf
        sub     sp, sp, #16     // 在栈上取4word空间储存局部变量
        ldr     r0, =scanfstr   // scanf argument 1: calc & pass
        // arg2-arg5对应地址递增，与ldmfd取值方式对应
        add     r1, sp, #0      // scanf argument 2: calc & pass
        add     r2, sp, #4      // scanf argument 3: calc & pass
        add     r3, sp, #8      // scanf argument 4: calc & pass
        add     r4, sp, #12     // scanf argument 5: calc
        stmfd   sp!, {r4}       // scanf argument 5:        pass 用栈传参
        bl      scanf           // 函数调用printf
        add     sp, #4          // Here stores scanf arg5, which is useless
        ldmfd   sp!, {r0-r3}    // r0=a, r1=b, r2=c, r3=d
        add     r4, r1, r0      // r4 = x = b+a 
        sub     r5, r2, r3      // r5 = y = c-d
.if:    cmp     r4, r5          // 比较x与y的大小关系
        bne     .else           // x != y时跳转到.else对应的代码部分
        bleq    sub             // x == y时执行的代码：调用sub函数，其参数a,b,c已经按调用约定置入r0-r2
        b       .endif          // x == y时不执行.else对应的代码部分，跳转到.endif
.else:  bl      acc             // x != y时执行的代码：调用acc函数，其参数a已经按调用约定置入r0
.endif: mov     r3, r0          // printf arg4: r3 = z
        ldr     r0, =printfstr2 // printf arg1: r0用ldr伪指令加载格式化字符串地址
        mov     r1, r4          // printf arg2: r1 = x 
        mov     r2, r5          // printf arg3: r2 = y
        bl      printf 
        mov     r0, #0          // main函数返回值0
        ldmfd   sp!, {lr}       // 恢复lr寄存器
        mov     pc, lr          // main函数返回

// sub函数入口
sub:    sub     r0, r0, r1      // r0 = x1 - x2
        sub     r0, r0, r2      // r0 = r0 - x3 = x1 - x2 - x3
        mov     pc, lr          // sub函数返回，返回值已按调用约定置入r0

// acc函数入口
acc:    mov     r1, #0          // r1 = i 初值0，按照调用约定r0-r3无需压栈保存
.loop:  add     r0, r1          // 循环体r = r + i 
        add     r1, #1          // 循环步进i++
        cmp     r1, #5          // 循环条件 i<=5
        ble     .loop           // 依循环条件跳转回循环体
        mov     pc, lr          // acc函数返回，返回值已按调用约定置入r0

// END
.end

